package com.sailing.xjpb.dict.translate.handler;

import com.google.common.collect.Maps;
import com.sailing.xjpb.common.SailingReflectionUtils;
import com.sailing.xjpb.common.web.translate.TranslateHandler;
import com.sailing.xjpb.dict.entity.bo.DictionaryBO;
import com.sailing.xjpb.dict.service.DictionaryService;
import com.sailing.xjpb.dict.translate.annotation.DictField;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.Field;
import java.util.*;

/**
 * 枚举翻译处理器：处理VO标注有@DictField注解的字段翻译
 *
 * @author YaoWei
 * createDate 2020/11/26
 */
@Slf4j
public class DictTranslateHandler implements TranslateHandler {

    @Autowired
    private DictionaryService dictionaryService;

    @Override
    public void doTranslate(Class<?> itemClass, List<Field> translateFields, Collection<?> datas) {
        try {
            // 获取需要翻译的枚举信息
            Map<String, List<DictionaryBO>> translateDicts = getTranslateDicts(translateFields);
            for (Field field : translateFields) {
                for (Object data : datas) {
                    DictField dictField = field.getAnnotation(DictField.class);
                    String dictType = dictField.dictType();
                    String dictNameField = dictField.dictNameField();
                    List<DictionaryBO> dictList = translateDicts.get(dictType);
                    String sourceFieldName = dictField.sourceField();
                    String targetFieldName = field.getName();
                    String splitter = dictField.splitter();
                    String dictCode = this.getValue(itemClass, data, sourceFieldName);
                    if (StringUtils.isBlank(dictCode)) {
                        continue;
                    }
                    String translatedValue = this.doTranslate(dictCode, splitter, dictNameField, dictList);
                    SailingReflectionUtils.setField(field, data, translatedValue);
                    if (log.isDebugEnabled()) {
                        log.debug("字典翻译：class={}==>sourceField={}->targetFieldName={}->value={}", itemClass,
                                sourceFieldName,
                                targetFieldName, translatedValue);
                    }


                }
            }
        } catch (Exception e) {
            log.error("字典翻译出错：{}", e.getMessage());
        }
    }

    @Override
    public SailingReflectionUtils.FieldFilter getTranslateFieldFilter() {
        return field -> field.getAnnotation(DictField.class) != null;
    }

    @Override
    public int getOrder() {
        return 1;
    }

    /**
     * 获取DictField配置的dictType属性对应的枚举信息
     *
     * @param fields 标注有DictField的枚举信息
     * @author YaoWei
     * createDate 2020年11月13日 下午3:41:59
     * editDate 2020年11月13日 下午3:41:59
     */
    private Map<String, List<DictionaryBO>> getTranslateDicts(List<Field> fields) {
        Map<String, List<DictionaryBO>> dictInfo = Maps.newHashMap();
        try {
            for (Field field : fields) {
                DictField translateField = field.getAnnotation(DictField.class);
                String dictType = translateField.dictType();
                // 地址枚举数据量太大了，不能一次性加载到内存中，需要单独翻译
                List<DictionaryBO> dictList = dictionaryService.queryByType(dictType);
                dictInfo.put(dictType, dictList);
            }
        } catch (Exception e) {
            log.warn("查询字典信息出错！", e);
        }
        return dictInfo;
    }

    /**
     * 获取翻译后的枚举值，如果没有翻译成功，返回code
     *
     * @param originDictCode 枚举codes
     * @param dictNameField  获取枚举中哪个字段的值作为翻译值
     * @param dictList       dictType对应的所有枚举
     * @author YaoWei
     * createDate 2020年11月13日 下午3:42:50
     * editDate 2020年11月13日 下午3:42:50
     */
    private String doTranslate(String originDictCode, String splitter, String dictNameField, List<DictionaryBO> dictList) {
        String[] dictCodes = originDictCode.split(splitter);
        List<String> dictValues = new ArrayList<>(dictCodes.length);
        for (String dictCode : dictCodes) {
            dictValues.add(this.doTranslate(dictCode, dictNameField, dictList));
        }
        return StringUtils.join(dictValues, splitter);
    }

    /**
     * 获取翻译后的枚举值，如果没有翻译成功，返回code
     *
     * @param dictCode      枚举code
     * @param dictNameField 获取枚举中哪个字段的值作为翻译值
     * @param dictList      dictType对应的所有枚举
     * @author YaoWei
     * createDate 2020年11月13日 下午3:42:50
     * editDate 2020年11月13日 下午3:42:50
     */
    private String doTranslate(String dictCode, String dictNameField, List<DictionaryBO> dictList) {
        Optional<DictionaryBO> optional = dictList.stream().filter(e -> Objects.equals(dictCode, e.getCode()))
                .findFirst();
        if (optional.isPresent()) {
            return this.doTranslate(optional.get(), dictNameField);
        }
        return dictCode;
    }

    /**
     * 根据用户指定的字段进行翻译
     *
     * @param dictionaryBO  查询到的枚举信息
     * @param dictNameField 枚举翻译返回值字段
     * @return 翻译后的枚举值
     */
    private String doTranslate(DictionaryBO dictionaryBO, String dictNameField) {
        if ("name".equals(dictNameField)) {
            // 兼容之前版本
            return dictionaryBO.getName();
        } else if ("fullName".equals(dictNameField)) {
            return dictionaryBO.getFullName();
        } else {
            return getValue(DictionaryBO.class, dictionaryBO, dictNameField);
        }
    }

    private String getValue(Class<?> itemClass, Object data, String sourceFieldName) {
        Field sourceField = SailingReflectionUtils.findAndMakeAccessible(itemClass, sourceFieldName);
        Object sourceFieldValue = SailingReflectionUtils.getField(sourceField, data);
        return Objects.toString(sourceFieldValue, null);
    }
}
